/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package bobbietalk.gui.blocks;

import bobbietalk.gui.ProgrammingBlock;
import bobbietalk.gui.blocks.parametrized.BlockFactory;
import java.awt.Rectangle;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;

/**
 *
 * @author roberto
 */
public class ProgramLoader {
    
    private BlockFactory blockFactory;
    private static int id;
    
    public ProgramLoader(BlockFactory blockFactory) {
        this.blockFactory = blockFactory;
    }
    
    public void sourceBlocks(Reader reader, List<ProgrammingBlock> program) throws IllegalAccessException, InstantiationException, ClassNotFoundException, SecurityException, InvocationTargetException, IOException, IllegalArgumentException, NoSuchMethodException {
        
        reader.mark(100000);
        HashMap<String, ProgrammingBlock> blocks = new HashMap<>();

        BufferedReader rd = new BufferedReader(reader);

        String line = rd.readLine();
        ProgrammingBlock b = null;

        while (line != null) {

            String l = line.replaceFirst(";", "");
            String[] s = l.split("=");

            if (s[0].equals("class")) {

                String className = s[1];

                if (!className.equals("GenericMiddleBlock")) {

                    b = createBlock(className);
                    

                } else {
                    b = null;
                }

            } else if (s[0].equals("type")) {

                if (b == null) {

                    b = blockFactory.newInstance(s[1]);
                    

                }


            } else if (s[0].equals("name")) {

                final String blockName = s[1];

                assignBlockName(b, blockName);
                blocks.put(b.getName(), b);

            } else if (s[0].equals("x")) {


                final String xStr = s[1];
                assignBlockX(b, xStr);

            } else if (s[0].equals("y")) {

                final String yStr = s[1];
                assignBlockY(b, yStr);

                

            } else if (s[0].equals("next") || s[0].equals("prev")) {
                // ignore at pass #1
            } else if (s[0].startsWith("attr.")) {

                b.setAttribute(s[0], s[1]);

            }

            line = rd.readLine();

        }

        // rd.close();

        reader.reset();

        rd = new BufferedReader(reader);

        line = rd.readLine();
        b = null;

        while (line != null) {

            String l = line.replaceFirst(";", "");
            String[] s = l.split("=");

            if (s[0].equals("class")) {
                // ignore
            } else if (s[0].equals("name")) {

                b = blocks.get(s[1]);

            } else if (s[0].equals("next")) {

                b.setNextBlock(blocks.get(s[1]));

            } else if (s[0].equals("prev")) {

                b.setPreviousBlock(blocks.get(s[1]));
            }

            line = rd.readLine();

        }

        rd.close();
        
        program.addAll(blocks.values());

        id++;
        
        
    }
    
    public static ProgrammingBlock createBlock(String className) throws NoSuchMethodException, InstantiationException, SecurityException, ClassNotFoundException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        ProgrammingBlock b;
        String cn = "bobbietalk.gui.blocks." + className;
        Class<?> clazz = ProgramLoader.class.getClassLoader().loadClass(cn);
        Constructor<?> constructor = clazz.getConstructor();
        b = (ProgrammingBlock) constructor.newInstance();

        return b;
    }
    
    public static void assignBlockName(ProgrammingBlock b, final String blockName) throws NumberFormatException {

        b.setName(blockName);

        String[] ss = blockName.split("-");

        int cid = Integer.parseInt(ss[1]);

        if (cid > id) {
            id = cid;
        }
        
    }

    public static void assignBlockX(ProgrammingBlock b, final String xStr) throws NumberFormatException {
        Rectangle bounds = b.getBounds();
        bounds.x = Integer.parseInt(xStr);
        b.setBounds(bounds);
    }

    public static void assignBlockY(ProgrammingBlock b, final String yStr) throws NumberFormatException {
        Rectangle bounds = b.getBounds();

        bounds.y = Integer.parseInt(yStr);
        b.setBounds(bounds);
    }

    public static int getId() {
        return id;
    }
    
    public static int nextId() {
        return id++;
    }
    
    public static void setId(int id) {
        ProgramLoader.id = id;
    }
    
}
